package com.template.utils.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Component
public class HashOps extends KeyOps {

    private final HashOperations<String, String, Object> hashOperations;

    @Autowired
    public HashOps(RedisTemplate<String, Object> redisTemplate) {
        super(redisTemplate);
        this.hashOperations = redisTemplate.opsForHash();
    }


    /**
     * <h4> Hash </h4>
     * 缓存键值对
     * <li> hset _key _field _value </li>
     */
    public void hSet(String key, String field, Object value) {
        hashOperations.put(key, field, value);
    }

    /**
     * <h4> Hash </h4>
     * 批量添加键值对
     * <li> hset _key _field1 _value1 _field2 _value2 </li>
     */
    public void hSet(String key, Map<String, Object> map) {
        hashOperations.putAll(key, map);
    }

    /**
     * <h4> Hash </h4>
     * 缓存键值对，若存在则保留旧值
     * <li> hsetnx _key _field _value </li>
     */
    public Boolean hSetNx(String key, String field, Object value) {
        return hashOperations.putIfAbsent(key, field, value);
    }

    /**
     * <h4> Hash </h4>
     * 获取指定 field 值
     * <li> hget _key _field </li>
     */
    public Object hGet(String key, String field) {
        return hashOperations.get(key, field);
    }

    /**
     * <h4> Hash </h4>
     * 获取指定的 key 的键值对
     * <li> hgetall _key </li>
     */
    public Map<String, Object> hGetAll(String key) {
        return hashOperations.entries(key);
    }

    /**
     * <h4> Hash </h4>
     * 批量获取指定 field 值
     * <li> hmget _key _field1 _field2 </li>
     */
    public List<Object> hMGet(String key, Collection<String> field) {
        return hashOperations.multiGet(key, field);
    }

    /**
     * <h4> Hash </h4>
     * 判断 field 是否存在
     * <li> hexists _key _field </li>
     */
    public Boolean hExists(String key, String field) {
        return hashOperations.hasKey(key, field);
    }

    /**
     * <h4> Hash </h4>
     * 获取 field 值的长度
     * <li> hstrlen _key _field </li>
     */
    public Long hStrlen(String key, String field) {
        return hashOperations.lengthOfValue(key, field);
    }

    /**
     * <h4> Hash </h4>
     * 获取 key 的键值对个数
     * <li> hlen _key </li>
     */
    public Long hLen(String key) {
        return hashOperations.size(key);
    }

    /**
     * <h4> Hash </h4>
     * 增加 field 值
     * <li> hincrby _key _field _num </li>
     *
     * @return 增加后的值
     */
    public Long hIncrBy(String key, String field, long num) {
        return hashOperations.increment(key, field, num);
    }

    /**
     * <h4> Hash </h4>
     * 增加 field 值
     * <li> hincrby _key _field _num </li>
     *
     * @return 增加后的值
     */
    public Double hIncrByFloat(String key, String field, double num) {
        return hashOperations.increment(key, field, num);
    }

    /**
     * <h4> Hash </h4>
     * 随机获取一个键名
     * <li> hrandfield _key </li>
     */
    public String hRandField(String key) {
        return hashOperations.randomKey(key);
    }

    /**
     * <h4> Hash </h4>
     * 随机获取多个键名
     * <li> hrandfield _key _count </li>
     */
    public List<String> hRandField(String key, long count) {
        return hashOperations.randomKeys(key, count);
    }

    /**
     * <h4> Hash </h4>
     * 随机获取一个键值对
     * <li> hrandfield _key 1 withvalues </li>
     */
    public Map.Entry<String, Object> hRandFieldWithValues(String key) {
        return hashOperations.randomEntry(key);
    }

    /**
     * <h4> Hash </h4>
     * 随机获取多个键值对
     * <li> hrandfield _key _count withvalues </li>
     */
    public Map<String, Object> hRandFieldWithValues(String key, long count) {
        return hashOperations.randomEntries(key, count);
    }

    /**
     * <h4> Hash </h4>
     * 迭代键值对
     * <li> hscan _key cursor [match _pattern] [count _count] </li>
     *
     * @return 记得 close
     */
    public Cursor<Map.Entry<String, Object>> hScan(String key, ScanOptions scanOptions) {
        return hashOperations.scan(key, scanOptions);
    }

    /**
     * <h4> Hash </h4>
     * 获取指定的 key 的所有键
     * <li> hkeys _key </li>
     */
    public Set<String> hKeys(String key) {
        return hashOperations.keys(key);
    }

    /**
     * <h4> Hash </h4>
     * 获取指定的 key 的所有值
     * <li> kvals _key </li>
     */
    public List<Object> hVals(String key) {
        return hashOperations.values(key);
    }

    /**
     * <h4> Hash </h4>
     * 删除指定 key 一个或者多个键
     * <li> hdel _key _field1 _field2 ... </li>
     */
    public Long hDel(String key, String... field) {
        return hashOperations.delete(key, (Object[]) field);
    }

    /**
     * <h4> Hash </h4>
     * 删除指定 key 一个或者多个键
     * <li> hdel _key _field1 _field2 ... </li>
     */
    public Long hDel(String key, Collection<String> field) {
        return hashOperations.delete(key, field.toArray());
    }

}
